package com.nantong.admin.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;

import com.nantong.admin.annotation.PermissionRegister;
import com.nantong.admin.domain.SysPermission;
import com.nantong.admin.domain.model.response.permission.SysPermissionVo;
import com.nantong.admin.service.ISysPermissionService;
import com.nantong.admin.util.LoginHelper;
import com.nantong.common.core.domain.R;
import com.nantong.common.mybatis.core.page.PageQuery;
import com.nantong.common.mybatis.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Set;

import cn.hutool.core.lang.tree.Tree;

/**
 * 权限管理
 *
 * @author nantong
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/system/permission")
@Tag(name = "权限管理", description = "权限管理相关接口")
@PermissionRegister(
    name = "权限管理", 
    key = "system:permission", 
    type = 2,  // 2=菜单
    path = "permission",
    component = "/views/Permission/PermissionView.vue",
    icon = "safety",
    sortOrder = 3,
    parentKey = "system"  // 父菜单是system
)
public class SysPermissionController {

    private final ISysPermissionService permissionService;

    /**
     * 获取权限列表
     */
    @GetMapping("/list")
    @Operation(summary = "获取权限列表", description = "获取系统权限列表")
    @SaCheckPermission("system:permission:list")
    @PermissionRegister(
            name = "权限列表查询",
            key = "system:permission:list",
            type = 3,  // 3=按钮
            remark = "查询权限数据列表"
    )
    public R<List<SysPermission>> list() {
        List<SysPermission> permissions = permissionService.list();
        return R.ok(permissions);
    }
    
    /**
     * 分页获取权限列表
     */
    @GetMapping("/page")
    @Operation(summary = "分页获取权限列表", description = "分页获取系统权限列表")
    @SaCheckPermission("system:permission:page")
    @PermissionRegister(
            name = "权限分页查询",
            key = "system:permission:page",
            type = 3,  // 3=按钮
            remark = "分页查询权限数据列表"
    )
    public TableDataInfo<SysPermission> page(PageQuery pageQuery) {
        return permissionService.selectPageList(pageQuery);
    }

    /**
     * 获取权限详情
     */
    @GetMapping("/{permissionId}")
    @Operation(summary = "获取权限详情", description = "根据权限ID获取权限详情")
    @SaCheckPermission("system:permission:query")
    @PermissionRegister(
            name = "权限详情查询",
            key = "system:permission:query",
            type = 3,  // 3=按钮
            remark = "查询权限数据详情"
            )
    public R<SysPermission> getInfo(@PathVariable Long permissionId) {
        SysPermission permission = permissionService.getById(permissionId);
        return R.ok(permission);
    }

    /**
     * 新增权限
     */
    @PostMapping
    @Operation(summary = "新增权限", description = "新增系统权限")
    @SaCheckPermission("system:permission:add")
    @PermissionRegister(
            name = "权限新增",
            key = "system:permission:add",
            type = 3,  // 3=按钮
            remark = "新增权限数据"
            )
    public R<Void> add(@RequestBody SysPermission permission) {
        if (!permissionService.checkPermissionNameUnique(permission)) {
            return R.fail("新增权限'" + permission.getPermissionName() + "'失败，权限名称已存在");
        }
        if (!permissionService.checkPermissionKeyUnique(permission)) {
            return R.fail("新增权限'" + permission.getPermissionName() + "'失败，权限标识已存在");
        }
        permissionService.save(permission);
        return R.ok();
    }

    /**
     * 修改权限
     */
    @PutMapping
    @Operation(summary = "修改权限", description = "修改系统权限")
    @SaCheckPermission("system:permission:edit")
    @PermissionRegister(
            name = "权限修改",
            key = "system:permission:edit",
            type = 3,  // 3=按钮
            remark = "修改权限数据"
            )
    public R<Void> edit(@RequestBody SysPermission permission) {
        if (!permissionService.checkPermissionNameUnique(permission)) {
            return R.fail("修改权限'" + permission.getPermissionName() + "'失败，权限名称已存在");
        }
        if (!permissionService.checkPermissionKeyUnique(permission)) {
            return R.fail("修改权限'" + permission.getPermissionName() + "'失败，权限标识已存在");
        }
        permissionService.updateById(permission);
        return R.ok();
    }

    /**
     * 删除权限
     */
    @DeleteMapping("/{permissionId}")
    @Operation(summary = "删除权限", description = "删除系统权限")
    @SaCheckPermission("system:permission:delete")
    @PermissionRegister(
            name = "权限删除",
            key = "system:permission:delete",
            type = 3,  // 3=按钮
            remark = "删除权限数据"
            )
    public R<Void> remove(@PathVariable Long permissionId) {
        permissionService.removeById(permissionId);
        return R.ok();
    }


    /**
     * 获取某个用户的权限
     */
    @GetMapping("/user/{userId}")
    @Operation(summary = "获取用户权限", description = "获取某个用户的权限")
    public R<Set<String>> getUserPermission(@PathVariable Long userId) {
        Set<String> permissions = permissionService.listPermissionKeysByUserId(userId);
        return R.ok(permissions);
    }

    /**
     * 加载对应角色菜单列表树
     *
     * @param roleId 角色ID
     */
    @SaCheckPermission("system:permission:tree")
    @GetMapping(value = "/rolePermissionTreeSelect/{roleId}")
    @Operation(summary = "获取角色菜单树", description = "根据角色ID获取角色菜单树")
    @PermissionRegister(
            name = "角色菜单树查询",
            key = "system:permission:tree",
            type = 3,  // 3=按钮
            remark = "查询角色菜单树数据"
            )
    public R<MenuTreeSelectVo> roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
        // 获取当前登录用户的ID
        Long currentUserId = LoginHelper.getUserId();
        
        // 获取当前用户可见的权限（基于用户自身权限过滤）
        List<SysPermissionVo> permissions = permissionService.listPermissions(currentUserId);

        // 获取指定角色已分配的权限ID列表
        List<Long> selectedPermissionIds = permissionService.listPermissionByRoleId(roleId);
        
        // 构建菜单树
        List<Tree<Long>> trees = permissionService.buildMenuTreeSelect(permissions);
        
        // 返回当前用户可见的权限树和目标角色已选权限
        MenuTreeSelectVo selectVo = new MenuTreeSelectVo(
                selectedPermissionIds,
                trees);
        return R.ok(selectVo);
    }


    public record MenuTreeSelectVo(List<Long> checkedKeys, List<Tree<Long>> menus) {
    }
    
    /**
     * 获取当前用户的菜单路由信息
     */
    @GetMapping("/getUserMenus")
    @Operation(summary = "获取用户菜单", description = "获取当前登录用户的菜单路由信息")
    public R<List<RouterVo>> getUserMenus() {
        Long userId = LoginHelper.getUserId();
        List<SysPermission> permissions = permissionService.selectPermissionsByUserId(userId);
        
        // 过滤出类型为菜单的权限，且状态为正常的
        List<SysPermission> menus = permissions.stream()
            .filter(p -> (p.getPermissionType() == 1 ||p.getPermissionType() == 2)  && p.getStatus() == 1)
            .sorted((a, b) -> {
                // 按照sortOrder排序，如果sortOrder为null则默认为0
                Integer aOrder = a.getSortOrder() == null ? 0 : a.getSortOrder();
                Integer bOrder = b.getSortOrder() == null ? 0 : b.getSortOrder();
                return aOrder.compareTo(bOrder);
            })
            .toList();
        
        // 构建路由信息
        List<RouterVo> routers = buildRouters(menus);
        return R.ok(routers);
    }
    
    /**
     * 构建前端路由所需要的菜单
     *
     * @param menus 菜单列表
     * @return 路由列表
     */
    private List<RouterVo> buildRouters(List<SysPermission> menus) {
        List<RouterVo> routers = new java.util.ArrayList<>();
        
        // 先找出顶级菜单
        List<SysPermission> topMenus = menus.stream()
            .filter(menu -> menu.getParentId() == null || menu.getParentId() == 0)
            .toList();
        
        // 处理顶级菜单
        for (SysPermission topMenu : topMenus) {
            RouterVo router = new RouterVo();
            router.setName(topMenu.getPermissionKey());
            router.setPath(topMenu.getPath());
            router.setComponent(topMenu.getComponent());
            router.setMeta(new MetaVo(
                topMenu.getPermissionName(),
                topMenu.getIcon(),
                topMenu.getIsHidden() != null && topMenu.getIsHidden()
            ));
            
            // 查找子菜单
            List<SysPermission> childMenus = menus.stream()
                .filter(menu -> topMenu.getPermissionId().equals(menu.getParentId()))
                .toList();
            
            // 如果存在子菜单，则递归构建子菜单路由
            if (!childMenus.isEmpty()) {
                router.setChildren(buildChildrenRouters(childMenus, menus));
            }
            
            routers.add(router);
        }
        
        return routers;
    }
    
    /**
     * 构建子菜单路由
     */
    private List<RouterVo> buildChildrenRouters(List<SysPermission> childMenus, List<SysPermission> allMenus) {
        List<RouterVo> childRouters = new java.util.ArrayList<>();
        
        for (SysPermission childMenu : childMenus) {
            RouterVo router = new RouterVo();
            router.setName(childMenu.getPermissionKey());
            router.setPath(childMenu.getPath());
            router.setComponent(childMenu.getComponent());
            router.setMeta(new MetaVo(
                childMenu.getPermissionName(),
                childMenu.getIcon(),
                childMenu.getIsHidden() != null && childMenu.getIsHidden()
            ));
            
            // 查找子菜单的子菜单
            List<SysPermission> grandChildMenus = allMenus.stream()
                .filter(menu -> childMenu.getPermissionId().equals(menu.getParentId()))
                .toList();
            
            // 如果存在子菜单，则递归构建子菜单路由
            if (!grandChildMenus.isEmpty()) {
                router.setChildren(buildChildrenRouters(grandChildMenus, allMenus));
            }
            
            childRouters.add(router);
        }
        
        return childRouters;
    }
    
    /**
     * 路由信息
     */
    @Data
    public static class RouterVo {
        /**
         * 路由名称
         */
        private String name;
        
        /**
         * 路由地址
         */
        private String path;
        
        /**
         * 组件路径
         */
        private String component;
        
        /**
         * 路由元信息
         */
        private MetaVo meta;
        
        /**
         * 子路由
         */
        private List<RouterVo> children;
    }
    
    /**
     * 路由元信息
     */
    @Data
    public static class MetaVo {
        /**
         * 标题
         */
        private String title;
        
        /**
         * 图标
         */
        private String icon;
        
        /**
         * 是否隐藏
         */
        private boolean hidden;
        
        public MetaVo(String title, String icon, boolean hidden) {
            this.title = title;
            this.icon = icon;
            this.hidden = hidden;
        }
    }
}
